#
# peerscape.profile.application
#
# Copyright 2009 Helsinki Institute for Information Technology
# and the authors.
#
# Authors:
#       Konrad Markus <konrad.markus@hiit.fi>
#       Ken Rimey <rimey@hiit.fi>
#

# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

from __future__ import with_statement
from peerscape.core.path import path_to_list

def update_content_from_application(db, appiid, ciid, parent_iid=None):
    """
    Update a content instance from the given appiid application.
    """
    with db.write_transaction():
        # copy over image
        img = db.get_profile_picture(appiid)
        if img:
            db.put(ciid, img, db.get(appiid, img))

        # clone the application
        app_keys = db.list(appiid, '/application')
        for k in app_keys:
            k = '/application/' + k
            db.put(ciid, k, db.get(appiid, k))

        # remove keys which are no longer needed
        content_keys = db.list(ciid, '/application')
        for k in content_keys:
            if not k in app_keys:
                db.delete(ciid, '/application/' + k)

        # copy over the contents of /template from application to content, dropping the '/template' prefix
        for path in db.list(appiid, '/template'):
            src = path_to_list(path)
            if parent_iid:
                dst = [(parent_iid if part == '^' else part) for part in src]
            else:
                dst = src

            value = db.get(appiid, ['template'] + src)
            db.put(ciid, dst, value)

        # return newly updated version
        system = db.get_json(ciid, '/application/prefs/system.json')
        if system:
            return system['version']
        
        return 0


def create_content_from_application(db, appiid, title, parent_iid=None,
                                    public_link=False):
    """
    Create a content instance for the given appiid application.

    Optionally attach it to the given parent_iid dataset.
    """
    with db.write_transaction():
        c = db.create_dataset(title, type='content')

        # insert the link to the application
        db.put(c, '/info/appiid', appiid)

        # copy over image
        img = db.get_profile_picture(appiid)
        if img:
            db.put(c, img, db.get(appiid, img))

        # clone the application
        for k in db.list(appiid, '/application'):
            k = '/application/' + k
            db.put(c, k, db.get(appiid, k))

        if parent_iid:
            db.add_link(parent_iid, c, public=public_link)
            db.put(c, '/info/parent', parent_iid)

            # if parent is a group, give group admins full control of the content dataset
            if db.get_dataset_type(parent_iid) == 'group':
                db.add_signing_policy(c, parent_iid, '/...', roles=['admin'])

        # copy over the contents of /template from application to content, dropping the '/template' prefix
        for path in db.list(appiid, '/template'):
            src = path_to_list(path)
            if parent_iid:
                dst = [(parent_iid if part == '^' else part) for part in src]
            else:
                dst = src

            value = db.get(appiid, ['template'] + src)
            db.put(c, dst, value)

        # return newly created content iid
        return c

PREFIX = '/admin/autoinstantiate/'

def request_content_from_application(db, appiid, title, public=False):
    my_iid = db.get_my_iid()
    path = PREFIX + appiid
    db.put_json(my_iid, path, appiid=appiid, title=title, public=public)

def autoinstantiate(db):
    try:
        my_iid = db.get_my_iid()
    except LookupError:
        return

    keys = db.list(my_iid, PREFIX)
    if not keys:
        return

    with db.write_transaction():
        for key in keys:
            path = PREFIX + key

            info = db.get_json(my_iid, path)
            if not info:
                continue

            appiid = info['appiid']
            if not db.get(appiid, '/info/modified'):
                db.subscribe(appiid)
            else:
                db.delete(my_iid, path)
                create_content_from_application(db, appiid,
                                                title=info['title'],
                                                parent_iid=my_iid,
                                                public_link=info['public'])
